package xml;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Array;

import functii.elementare.Constanta;
import functii.elementare.Necunoscuta;
import functii.trigonometrice.Cos;
import functii.trigonometrice.Sin;

import operatori.Cat;
import operatori.Minus;
import operatori.Plus;
import operatori.Produs;

import Arbore.ArboreFunctional;
import Arbore.Nod;

public class LoadXML {
	protected ArboreFunctional a;
	protected Nod n;
	protected FileReader fstream; 
	protected BufferedReader in;
	protected Array[] lista;
	protected int dim;
	
	public LoadXML(String fisier) throws IOException {
		fstream = new FileReader (fisier);
		in = new BufferedReader (fstream);
		lista = new Array [100];
		read();
		creareArbore();
		in.close();
		a = new ArboreFunctional(lista[0].getNod());
	}
	
	public ArboreFunctional getArbore() {
		return a;
	}
	
	public void read() throws IOException {
		String sir = in.readLine();
		int index = 0, i = -1;
		double valoare = 0;
		sir = in.readLine();
		
		while (sir!=null) {
			if (sir.indexOf('/') == -1) {
				i++;
				index = getNivel(sir);
				if(sir.indexOf("Constanta")!=-1) 
					valoare = getValoare(sir);
				sir = prelucrareSir (sir);
				if(sir.equals("Plus"))
					n = new Plus();
				else if(sir.equals("Minus"))
					n = new Minus();
				else if(sir.equals("Produs"))
					n = new Produs();
				else if(sir.equals("Cat"))
					n = new Cat();
				else if(sir.equals("Sin"))
					n = new Sin();
				else if(sir.equals("Cos"))
					n = new Cos();
				else if(sir.equals("Necunoscuta"))
					n = new Necunoscuta();
				else if(sir.equals("Constanta")) {
					n = new Constanta();
					((Constanta)n).setCt(valoare);
				}
				lista[i] = new Array(n, index);
			}
			sir = in.readLine();
		}
		dim = i;
		System.out.println();
		System.out.println();
	}
	
	public String prelucrareSir(String sir) throws IOException {
		sir = sir.trim();
		int index = 0, index1;
		if((index1 = sir.indexOf(' '))!= -1)
			index = index1;
		else
			index = sir.indexOf('>');
		String sir2 = sir.substring(1, index);
		return sir2;
	}
	
	public int getNivel (String sir) throws IOException {
		sir = sir.trim();
		int index = 0, index1, index2;
		if((index1 = sir.indexOf("id = \""))!= -1)
			index = index1;
		else
			System.out.println("Eroare: Format xml gresit!");
		index2 = sir.substring(index + 4).indexOf('\"');
		sir = sir.substring(index + 4, index + 4 + index2);
		return Integer.parseInt(sir);
	}
	
	public double getValoare (String sir) {
		sir = sir.trim();
		int index = 0, index1, index2;
		if((index1 = sir.indexOf("val=\"")) != -1)
			index = index1;
		else
			System.out.println("Eroare: Format xml gresit!");
		index2 = sir.substring(index + 5).indexOf('\"');
		sir = sir.substring(index + 5, index + 5 + index2);
		return Double.parseDouble(sir);
	}
	
	public void creareArbore() {
		int nivel, j, nivel2, nivel1;
		for(int i = 0;i <= dim; i++) { //start - for - 0
			nivel = lista[i].getIndex();
			nivel1 = lista[i].getIndex();
			if(!lista[i].getNod().getClass().getName().equals("functii.elementare.Constanta") 
			&& !lista[i].getNod().getClass().getName().equals("functii.elementare.Necunoscuta"))
			{//start - if -0
				for(j = i; j < dim && (nivel2 = lista[j].getIndex()) >= nivel1; j++) { //start-for-1
					if(lista[j].getIndex() == nivel + 1) {//start - if - 1
						if(lista[i].getNod().getFStang() == null) {//start - if - 2
							String nume = lista[j].getNod().getClass().getName();
							if(nume.equals("operatori.Plus") || 
							   nume.equals("operatori.Minus") ||
							   nume.equals("operatori.Produs") ||
							   nume.equals("operatori.Cat") ||
							   nume.equals("operatori.Putere") ||
							   nume.equals("functii.elementare.Constanta") ||
							   nume.equals("functii.elementare.Necunoscuta") ||
							   nume.equals("functii.trigonometrice.Sin") ||
							   nume.equals("functii.trigonometrice.Cos"))
								lista[i].getNod().setfStang(lista[j].getNod());
							else 
								System.out.println("error la stanga: "+lista[i].getNod().getClass().getName());
						}//end - if - 2
						else {//start - else
							String name = lista[j].getNod().getClass().getName();
							if(name.equals("operatori.Plus") || 
							   name.equals("operatori.Minus") ||
							   name.equals("operatori.Produs") ||
							   name.equals("operatori.Cat") ||
							   name.equals("operatori.Putere") ||
							   name.equals("functii.elementare.Constanta") ||
							   name.equals("functii.elementare.Necunoscuta") ||
							   name.equals("functii.trigonometrice.Sin") ||
							   name.equals("functii.trigonometrice.Cos"))
								lista[i].getNod().setFDrept(lista[j].getNod());
							else
								System.out.println("error la dreapta: "+lista[i].getNod().getClass().getName());
						}//end-else
					}//end-if-1
					nivel1 = nivel2;
				}//end-for-1
				if(lista[j].getIndex() == nivel + 1) {//start - if - 3
					if(lista[i].getNod().getfStang() == null) {//start - if - 4
						String nume = lista[j].getNod().getClass().getName();
						if(nume.equals("operatori.Plus") || 
						   nume.equals("operatori.Minus") ||
						   nume.equals("operatori.Produs") ||
						   nume.equals("operatori.Cat") ||
						   nume.equals("operatori.Putere") ||
						   nume.equals("functii.elementare.Constanta") ||
						   nume.equals("functii.elementare.Necunoscuta") ||
						   nume.equals("functii.trigonometrice.Sin") ||
						   nume.equals("functii.trigonometrice.Cos"))
							lista[i].getNod().setfStang(lista[j].getNod());
						else
							System.out.println("error la stanga: "+lista[i].getNod().getClass().getName());
					}//end-if-4
					else {
						String name = lista[j].getNod().getClass().getName();
						if(name.equals("operatori.Plus") || 
						   name.equals("operatori.Minus") ||
						   name.equals("operatori.Produs") ||
						   name.equals("operatori.Cat") ||
						   name.equals("operatori.Putere") ||
						   name.equals("functii.elementare.Constanta") ||
						   name.equals("functii.elementare.Necunoscuta") ||
						   name.equals("functii.trigonometrice.Sin") ||
						   name.equals("functii.trigonometrice.Cos"))
							lista[i].getNod().setfDrept(lista[j].getNod());
						else
							System.out.println("error la dreapta: "+lista[i].getNod().getClass().getName());
					}
				}//end-if-3
			}//end-if-0
		}//end-for-0
	}//end-method
 }//end-class
